package com.maker.generator.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.dwork.base.controller.BaseController;
import com.dwork.base.controller.entity.BaseResultObject;
import com.dwork.base.pagination.Page;
import com.dwork.base.pagination.Pagination;
import com.dwork.base.validate.groups.DEFAULT;
import com.maker.generator.controller.MetaGenObjController;
import com.maker.generator.dao.MetaGenObjDao;
import com.maker.generator.entity.MetaGenAttr;
import com.maker.generator.entity.MetaGenConfig;
import com.maker.generator.entity.MetaGenConfigItem;
import com.maker.generator.entity.MetaGenDBInfo;
import com.maker.generator.entity.MetaGenField;
import com.maker.generator.entity.MetaGenObj;
import com.maker.generator.entity.MetaGenTable;
import com.maker.generator.service.IGenService;

public class TransEntityUtil {
	/**
	 * 输出实体类代码
	 * @param obj
	 * @param options
	 * @return
	 */
	public static String generateEntityString(MetaGenObj obj,Map<String,String> options){
		List<String> objCodeList = new ArrayList<String>();
		if(options == null){
			options = new HashMap<String,String>();
		}
		options = fixConfig(obj.getConfig(),options);
		List<String> objGenInfoList = new ArrayList<String>();
		objGenInfoList = formatCommentList("@author rainbow_generator");
		String packageInfo = "package "+obj.getObjPackageName()+" ;";
		List<String> objImportList = new ArrayList<String>();
		List<String> objCommentList = new ArrayList<String>();
		
		String objHeader = "public class "+obj.getObjName() + " implements Serializable{";
		List<String> attrBodyList = new ArrayList<String>();
		List<String> attrGetsList = new ArrayList<String>();
		List<String> attrSetsList = new ArrayList<String>();
		String objTail = "}";
		if(obj.getObjComment()!=null && !"".equals(obj.getObjComment())){
			objCommentList = formatCommentList(obj.getObjComment());
		}

		for(MetaGenAttr attr:obj.getMetaAttrs()){
			Map<String,List<String>> attrMap = new HashMap<String,List<String>>();
			attrMap = generateAttr4Obj(obj,attr,options);
			if(attrMap.get("importList")!=null && attrMap.get("importList").size()>0){
				for(String item : attrMap.get("importList")){
					if(!objImportList.contains(item)){
						objImportList.add(item);
					}
				}
			}
			attrBodyList.addAll(attrMap.get("commentList"));
			attrBodyList.addAll(attrMap.get("validateList"));
			attrBodyList.addAll(attrMap.get("attrBody"));
			attrGetsList.addAll(attrMap.get("getsList"));
			attrSetsList.addAll(attrMap.get("setsList"));
		}
		
		objCodeList.addAll(objGenInfoList);
		objCodeList.add(packageInfo);
		objCodeList.addAll(objImportList);
		objCodeList.addAll(objCommentList);
		objCodeList.add(objHeader);
		objCodeList.addAll(attrBodyList);
		objCodeList.addAll(attrGetsList);
		objCodeList.addAll(attrSetsList);
		objCodeList.add(objTail);
		return TransUtil.arrayList2Code(objCodeList,"\r\n");
	}
	
	public static String generateMapperString(MetaGenObj obj,MetaGenDBInfo dbInfo,Map<String,String> options){
		List<String> result = new ArrayList<String>();
		result.add("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
		result.add("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >");
		result.add("<mapper namespace="+obj.getObjTypeName()+">");
		//纯实体map
				List<String> pureEntityMapper = new ArrayList<String>();
				pureEntityMapper.add("<resultMap id=\""+obj.getObjName()+"PureMap\" type=\""+obj.getObjName()+"\">");
				//带关联对象的实体map
				List<String> entityWithRelationMapper = new ArrayList<String>();
				//关联对象实体map的map
				Map<String,List<String>> refRelationMapper = new HashMap<String,List<String>>();
				Map<String,List<String>> attrSqlMap = new HashMap<String,List<String>>();
				Map<String,List<String>> refAttrSelectorMap = new HashMap<String,List<String>>();
				Map<String,List<String>> objSelectorMap = new HashMap<String,List<String>>();
				entityWithRelationMapper.add("<resultMap id=\""+obj.getObjName()+"Map\" type=\""+obj.getObjName()+"\">");
				String tableName = "";
				List<String> baseColumn = new ArrayList<String>();
				List<String> baseWhere = new ArrayList<String>();
				List<String> insert = new ArrayList<String>();
				List<String> insert_attrList = new ArrayList<String>();
				List<String> insert_valueList = new ArrayList<String>();
				insert_valueList.add(") values (");
				List<String> update = new ArrayList<String>();
				
				List<String> update_FieldList = new ArrayList<String>();
				String updateWhere = new String();
				tableName = getObjConfigItemValueByKey(obj,MetaGenConfig.TABLE_NAME);
				if(("".equals(tableName)) || (tableName == null)){
					tableName =TransUtil.obj2TableName(obj);
				}
				insert.add("<insert id=\"save\" parameterType=\""+obj.getObjName()+"\" useGeneratedKeys=\"false\"  keyProperty=\"id\" keyColumn=\"id\">");
				if(MetaGenDBInfo.DBTYPE_MYSQL.equals(dbInfo.getDbType())){
					//mysql的不用加这个selectKey
				}else{
					insert.add("<selectKey resultType=\"java.lang.Long\" keyProperty=\"id\" order=\"BEFORE\">");
					insert.add("	select sq_"+tableName+"_id.nextval as id from dual");
					insert.add("</selectKey>");
				}
				insert_attrList.add("insert into "+tableName+"(");
				update.add("<update id = \"update\" parameterType=\""+obj.getObjName()+"\">");
				update.add("update "+tableName+" set");
				baseColumn.add("<sql id=\"Base_Column_List\">");
				baseWhere.add("<sql id=\"Base_Where_Clause\">");
				baseWhere.add("	<where>");
				baseWhere.add("		<trim prefixOverrides=\"and\">");
				
				for(MetaGenAttr attr : obj.getMetaAttrs()){
					switch (attr.getRelationShip()){
						case MetaGenAttr.RELATIONSHIP_1N:
							break;
						case MetaGenAttr.RELATIONSHIP_NN:
							break;
						case MetaGenAttr.RELATIONSHIP_N1:
							entityWithRelationMapper.add("<association javaType=\""+attr.getAttrShortTypeName()+"\" property=\""+attr.getAttrName()+"\" column=\""+attr.getAttrName()+"Id\" select=\"find"+attr.getAttrShortTypeName()+"ById\" />");
							insert_attrList.add("	"+attr.getAttrName()+"Id ,");
							MetaGenObj refObj = new MetaGenObj();
							//TODO 先需要根据属性的全类型，去查找元对象
							break;
						default:
							//对应的数据库类型
							String fieldType = getAttrConfigItemValueByKey(attr,MetaGenConfig.FIELD_TYPE);
							if(MetaGenDBInfo.DBTYPE_ORACLE.equals(dbInfo.getDbType())){
								if(("".equals(fieldType)) || (fieldType == null)){
									fieldType = TransUtil.javaType2OracleFieldType(attr.getAttrType());
								}
							}else{
								if(("".equals(fieldType)) || (fieldType == null)){
									fieldType = TransUtil.javaType2MysqlFieldType(attr.getAttrType());
								}
							}
							if("ID".equals(attr.getAttrName()) || "id".equals(attr.getAttrName())){
								pureEntityMapper.add("	<id column=\"id\" property=\"id\" />");
								entityWithRelationMapper.add("	<id column=\"id\" property=\"id\" />");
								baseWhere.add("			<if test=\"id != null\"> and id = #{id}</if>");
								updateWhere = "	id=#{id, jdbcType="+fieldType+"}";
							}else{
								pureEntityMapper.add("	<result column=\""+attr.getAttrName()+"\" property=\""+attr.getAttrName()+"\" />");
								entityWithRelationMapper.add("	<result column=\""+attr.getAttrName()+"\" property=\""+attr.getAttrName()+"\" />");
								baseWhere.add("			<if test=\""+attr.getAttrName()+" != null\">and "+attr.getAttrName()+" = #{"+attr.getAttrName()+"}</if>");
								if("java.lang.String".equals(attr.getAttrType())){
									if(MetaGenDBInfo.DBTYPE_ORACLE.equals(dbInfo.getDbType())){
										baseWhere.add("			<if test=\""+attr.getAttrName()+"Like != null\">and "+attr.getAttrName()+" like  \'%\'||#{"+attr.getAttrName()+"}||\'%\'</if>");
									}else{
										baseWhere.add("			<if test=\""+attr.getAttrName()+"Like != null\">and "+attr.getAttrName()+" like CONCAT(\"%\",#{"+attr.getAttrName()+"Like},\"%\")</if>");
									}
								}
								update_FieldList.add("	"+attr.getAttrName()+" = #{"+attr.getAttrName()+", jdbcType="+fieldType+"},");
							}
							insert_valueList.add("	#{"+attr.getAttrName()+", jdbcType="+fieldType+"},");
							insert_attrList.add("	"+attr.getAttrName()+" ,");
							baseColumn.add("	"+attr.getAttrName()+" as "+attr.getAttrName()+" ,");
							//baseWhere.add("			<if test=\"id != null\"> and id = #{id}</if>");
							break;
					}
				}
				if(baseColumn.size()>0){
					String baseColumnTailer = baseColumn.get(baseColumn.size()-1);
					baseColumnTailer = baseColumnTailer.substring(0, baseColumnTailer.length()-1);
					baseColumn.remove(baseColumn.size()-1);
					baseColumn.add(baseColumnTailer);
					baseColumn.add("</sql>");
				}
				
				
				if(insert_attrList.size()>0){
					String insert_AttrTailer = insert_attrList.get(insert_attrList.size()-1);
					insert_AttrTailer = insert_AttrTailer.substring(0, insert_AttrTailer.length()-1);
					insert_attrList.remove(insert_attrList.size()-1);
					insert_attrList.add(insert_AttrTailer);
				}
				
				
				if(insert_valueList.size()>0){
					String insert_ValueTailer = insert_valueList.get(insert_valueList.size()-1);
					insert_ValueTailer = insert_ValueTailer.substring(0, insert_ValueTailer.length()-1);
					insert_valueList.remove(insert_valueList.size()-1);
					insert_valueList.add(insert_ValueTailer);
					insert_valueList.add(")");
					insert.addAll(insert_attrList);
					insert.addAll(insert_valueList);
					insert.add("</insert>");
				}
				if(update_FieldList.size()>0){
					String update_ColumnTailer = update_FieldList.get(update_FieldList.size()-1);
					update_ColumnTailer = update_ColumnTailer.substring(0, update_ColumnTailer.length()-1);
					update_FieldList.remove(update_FieldList.size()-1);
					update_FieldList.add(update_ColumnTailer);
					update.addAll(update_FieldList);
					update.add("where");
					update.add(updateWhere);
				}
				baseWhere.add("		</trim>");
				baseWhere.add("	</where>");
				baseWhere.add("	<if test=\"sorting != null\">order by ${sorting}</if>");
				baseWhere.add("</sql>");
				pureEntityMapper.add("</resultMap>");
			result.addAll(pureEntityMapper);
			result.addAll(baseColumn);
			result.addAll(baseWhere);
			result.addAll(insert);
			result.addAll(update);
			result.add("</mapper>");
			
		return TransUtil.arrayList2Code(result,"\r\n");
	}
	
	public static MetaGenTable generateTableInfo(MetaGenObj obj,Map<String,String> options){
		if(options == null){
			options = new HashMap<String,String>();
		}
		options = fixConfig(obj.getConfig(),options);
		MetaGenTable table = new MetaGenTable();
		String tablePrefix = "";
		if(options.get(MetaGenTable.CFG_KEY_PREFIX)!=null){
			tablePrefix = options.get(MetaGenTable.CFG_KEY_PREFIX);
		}
		table.setTableName(tablePrefix+obj.getObjName().toLowerCase());
		if(options.get(MetaGenTable.CFG_KEY_COMMENT)!=null){
			table.setTableComment(options.get(MetaGenTable.CFG_KEY_COMMENT));
		}else{
			table.setTableComment(obj.getObjComment());
		}
		if(options.get(MetaGenTable.CFG_KEY_WORKSPACE)!=null){
			table.setTableWorkSpace(options.get(MetaGenTable.CFG_KEY_WORKSPACE));
		}else{
			table.setTableWorkSpace("Custom_TS");
		}
		if(options.get(MetaGenTable.CFG_KEY_CE)!=null){
			table.setCharacterEncoding(options.get(MetaGenTable.CFG_KEY_CE));
		}
		List<String> sqlList = new ArrayList<String>();
		sqlList.add("create table "+table.getTableName()+" (");
		
		List<String> commentList = new ArrayList<String>();
		
		List<MetaGenField> fields = new ArrayList<MetaGenField>();
		for(int i=0;i<obj.getMetaAttrs().size();i++){
			MetaGenAttr attr = obj.getMetaAttrs().get(i);
			Map<String,String> attrOptions = new HashMap<String,String>();
			attrOptions = fixConfig(attr.getConfig(),options);
			
			if(MetaGenAttr.RELATIONSHIP_1N.equals(attr.getRelationShip()) || MetaGenAttr.RELATIONSHIP_NN.equals(attr.getRelationShip())){
				//类与属性的关系为1对多时:属性所对应的表中关联类的主键。多对多时，需要引入中间表，来关联双方主键。
				//故在类所对应的表元数据中，不需要记录该字段
			}else if(MetaGenAttr.RELATIONSHIP_N1.equals(attr.getRelationShip())){
				MetaGenField field = new MetaGenField();
				if(attrOptions.get(MetaGenField.CFG_KEY_NAME)!=null){
					field.setFieldName(attrOptions.get(MetaGenField.CFG_KEY_NAME));
				}else{
					field.setFieldName(attr.getAttrName()+"_id");
				}
				if(attrOptions.get(MetaGenField.CFG_KEY_COMMENT)!=null){
					field.setFieldComment(attrOptions.get(MetaGenField.CFG_KEY_COMMENT));
				}else{
					field.setFieldComment(attr.getAttrComment());
				}
				//field.setGenTable(table);
				fields.add(field);
				//comment on column GEN_OBJ.id  is '主键';
				commentList.add("comment on column "+table.getTableName()+"."+attr.getAttrName().toLowerCase()+"  is \'"+attr.getAttrComment()+"\';");
				if(i == (obj.getMetaAttrs().size()-1)){
					sqlList.add("	"+field.getFieldName().toLowerCase()+"	NUMBER");
				}else{
					sqlList.add("	"+field.getFieldName().toLowerCase()+"	NUMBER,");
				}
				
			}else{
				//普通关系
				MetaGenField field = new MetaGenField();
				if(attrOptions.get(MetaGenField.CFG_KEY_NAME)!=null){
					field.setFieldName(attrOptions.get(MetaGenField.CFG_KEY_NAME));
				}else{
					field.setFieldName(attr.getAttrName());
				}
				if(attrOptions.get(MetaGenField.CFG_KEY_COMMENT)!=null){
					field.setFieldComment(attrOptions.get(MetaGenField.CFG_KEY_COMMENT));
				}else{
					field.setFieldComment(attr.getAttrComment());
				}
				if(attrOptions.get(MetaGenField.CFG_KEY_TYPE)!=null){
					field.setFieldType(attrOptions.get(MetaGenField.CFG_KEY_TYPE));
				}else{
					
					if(MetaGenDBInfo.DBTYPE_ORACLE.equals(attrOptions.get(MetaGenDBInfo.CFG_KEY_DBTYPE))){
						field.setFieldType(jdbcType2OracleType(javaType2JdbcType(attr.getAttrType())));
					}else if(MetaGenDBInfo.DBTYPE_MYSQL.equals(attrOptions.get(MetaGenDBInfo.CFG_KEY_DBTYPE))){
						field.setFieldType(jdbcType2MysqlType(javaType2JdbcType(attr.getAttrType())));
					}else{
						//默认用oracle的
						field.setFieldType(jdbcType2OracleType(javaType2JdbcType(attr.getAttrType())));
					}
				}
				if(attrOptions.get(MetaGenField.CFG_KEY_LENGTH)!=null){
					field.setFieldLength(attrOptions.get(MetaGenField.CFG_KEY_LENGTH));
				}
				//field.setGenTable(table);
				fields.add(field);
				String lengthString = "";
				if(field.getFieldLength() !=null && !"".equals(field.getFieldLength())){
					lengthString = "("+field.getFieldLength()+")";
				}
				if(i == (obj.getMetaAttrs().size()-1)){
					sqlList.add("	"+field.getFieldName()+"	"+lengthString);
				}else{
					sqlList.add("	"+field.getFieldName()+"	"+lengthString+",");
				}
				commentList.add("comment on column "+table.getTableName()+"."+attr.getAttrName().toLowerCase()+"  is \'"+attr.getAttrComment()+"\';");
				
			}	
		}
		table.setGenFields(fields);
		sqlList.add(")");
		if(MetaGenDBInfo.DBTYPE_MYSQL.equals(options.get(MetaGenDBInfo.CFG_KEY_DBTYPE))){
			//mysql不需要表空间
		}else{
			
			sqlList.add("tablespace "+table.getTableWorkSpace());
			sqlList.add("	pctfree 10");
			sqlList.add("	initrans 1");
			sqlList.add("	maxtrans 255");
			sqlList.add("	storage");
			sqlList.add("	(");
			sqlList.add("		initial 64K");
			sqlList.add("		minextents 1");
			sqlList.add("		maxextents unlimited");
			sqlList.add("	)");
		}
		sqlList.add(";");
		if(MetaGenDBInfo.DBTYPE_MYSQL.equals(options.get(MetaGenDBInfo.CFG_KEY_DBTYPE))){
			//mysql不需要表空间
		}else{
			sqlList.add("-- Add sequence");
			sqlList.add("create sequence SQ_"+table.getTableName()+"_ID");
			sqlList.add("	minvalue 1");
			sqlList.add("	maxvalue 999999999");
			sqlList.add("	start with 1");
			sqlList.add("	increment by 1");
			sqlList.add("	cache 20;");
		}
		sqlList.add("-- Add comments to the columns");
		sqlList.addAll(commentList);
		
		table.setGeneratedSql(TransUtil.arrayList2Code(sqlList,"\r\n"));
		return table;
	}
	

	/**
	 * 输出DAO类代码
	 * @param obj
	 * @param options
	 * @return
	 */
	public static String generateDAOString(MetaGenObj obj,Map<String,String> options){
		List<String> result = new ArrayList<String>();
		result.add("package	"+obj.getObjPackageName()+".dao;");
		result.add("import org.springframework.stereotype.Repository;");
		result.add("import com.dwork.base.mybatis.dao.BaseDao;");
		result.add("import "+obj.getObjPackageName()+".entity."+obj.getObjName()+";");
		result.add("@Repository");
		result.add("public class "+obj.getObjPackageName()+"DAO	extends BaseDao<"+obj.getObjName()+", Long>{");
		result.add("");
		result.add("}");
		return TransUtil.arrayList2Code(result,"\r\n");
	}
	
	/**
	 * 输出IService类代码
	 * @param obj
	 * @param options
	 * @return
	 */
	public static String generateIServiceString(MetaGenObj obj,Map<String,String> options){
		List<String> result = new ArrayList<String>();
		result.add("package	"+obj.getObjPackageName()+".service;");
		result.add("import java.util.List;");
		result.add("import java.util.Map;");
		result.add("import com.dwork.base.pagination.Page;");
		result.add("import com.dwork.base.pagination.Pagination;");
		result.add("import "+obj.getObjPackageName()+".entity."+obj.getObjName()+";");
		result.add("public interface I"+obj.getObjName()+"Service {");
		
		result.add("/**");
		result.add("* 分页查询"+obj.getObjComment());
		result.add("* @param page	分页信息");
		result.add("* @param paramsMap	查询参数");
		result.add("* @return 分页数据");
		result.add("*/");
		result.add("public Pagination<"+obj.getObjName()+"> query"+obj.getObjName()+"Page(Page page, Map<String,Object> paramsMap);");
		
		result.add("/**");
		result.add("* 列表查询"+obj.getObjComment());
		result.add("* @param page	分页信息");
		result.add("* @param paramsMap	查询参数");
		result.add("* @return 列表数据");
		result.add("*/");
		result.add("public List<"+obj.getObjName()+"> query"+obj.getObjName()+"List(Map<String,Object> paramsMap);");
		
		
		result.add("/**");
		result.add("* 新增"+obj.getObjComment());
		result.add("* @param entity	");
		result.add("* @return ");
		result.add("*/");
		result.add("public "+obj.getObjName()+" save("+obj.getObjName()+" entity);");
		
		result.add("/**");
		result.add("* 更新"+obj.getObjComment());
		result.add("* @param entity	");
		result.add("* @return ");
		result.add("*/");
		result.add("public "+obj.getObjName()+" update("+obj.getObjName()+" entity);");
		
		result.add("/**");
		result.add("* 根据ID删除"+obj.getObjComment());
		result.add("* @param id	");
		result.add("* @return ");
		result.add("*/");
		result.add("public Boolean  delete"+obj.getObjName()+"ById(Long id);");
		
		result.add("/**");
		result.add("* 根据ids删除"+obj.getObjComment());
		result.add("* @param ids	");
		result.add("* @return ");
		result.add("*/");
		result.add("public Boolean  delete"+obj.getObjName()+"ByIds(List<Long> ids);");
		
		
		result.add("/**");
		result.add("* 根据ID获取"+obj.getObjComment());
		result.add("* @param id	");
		result.add("* @return ");
		result.add("*/");
		result.add("public "+obj.getObjName()+" find("+obj.getObjName()+"ById(Long id);");

		return TransUtil.arrayList2Code(result,"\r\n");
	}
	/**
	 * 输出ServiceImpl类代码
	 * @param obj
	 * @param options
	 * @return
	 */
	public static String generateServiceImplString(MetaGenObj obj,Map<String,String> options){
		List<String> result = new ArrayList<String>();
		result.add("package	"+obj.getObjPackageName()+".service.impl;");
		result.add("import java.util.List;");
		result.add("import java.util.Map;");
		result.add("import com.dwork.base.pagination.Page;");
		result.add("import com.dwork.base.pagination.Pagination;");
		result.add("import org.springframework.beans.factory.annotation.Autowired;");
		result.add("import org.springframework.stereotype.Service;");
		result.add("import org.springframework.transaction.annotation.Transactional;");
		
		
		result.add("import "+obj.getObjPackageName()+".entity."+obj.getObjName()+";");
		result.add("import "+obj.getObjPackageName()+".dao."+obj.getObjName()+"DAO;");
		result.add("import "+obj.getObjPackageName()+".service.I"+obj.getObjName()+"Service;");
		
		result.add("@Service");
		result.add("public class "+obj.getObjName()+"ServiceImpl implements I"+obj.getObjName()+"Service {");
		result.add("@Autowired");
		result.add("private "+obj.getObjName()+"DAO "+TransUtil.lowerCase(obj.getObjName())+"DAO ");
		
		result.add("/**");
		result.add("* 分页查询"+obj.getObjComment());
		result.add("* @param page	分页信息");
		result.add("* @param paramsMap	查询参数");
		result.add("* @return 分页数据");
		result.add("*/");
		result.add("public Pagination<"+obj.getObjName()+"> query"+obj.getObjName()+"Page(Page page, Map<String,Object> paramsMap){");
		result.add("	Pagination<"+obj.getObjName()+"> "+TransUtil.lowerCase(obj.getObjName())+"Page = "+TransUtil.lowerCase(obj.getObjName())+"Dao.findByPage(page,paramMap);");
		result.add("	return "+TransUtil.lowerCase(obj.getObjName())+"Page;");
		result.add("}");
				
		result.add("/**");
		result.add("* 列表查询"+obj.getObjComment());
		result.add("* @param page	分页信息");
		result.add("* @param paramsMap	查询参数");
		result.add("* @return 列表数据");
		result.add("*/");
		result.add("public List<"+obj.getObjName()+"> query"+obj.getObjName()+"List(Map<String,Object> paramsMap){");
		result.add("	List<"+obj.getObjName()+"> "+TransUtil.lowerCase(obj.getObjName())+"List = "+TransUtil.lowerCase(obj.getObjName())+"Dao.findByList(paramMap);");
		result.add("	return "+TransUtil.lowerCase(obj.getObjName())+"List;");
		result.add("}");
		
		result.add("/**");
		result.add("* 新增"+obj.getObjComment());
		result.add("* @param entity	");
		result.add("* @return ");
		result.add("*/");
		result.add("@Transactional");
		result.add("public "+obj.getObjName()+" save("+obj.getObjName()+" entity){");
		result.add("	this."+TransUtil.lowerCase(obj.getObjName())+"Dao.save(entity);");
		result.add("	return entity");
		result.add("}");
		
		result.add("/**");
		result.add("* 更新"+obj.getObjComment());
		result.add("* @param entity	");
		result.add("* @return ");
		result.add("*/");
		result.add("@Transactional");
		result.add("public "+obj.getObjName()+" update("+obj.getObjName()+" entity){");
		result.add("	this."+TransUtil.lowerCase(obj.getObjName())+"Dao.update(entity);");
		result.add("	return entity");
		result.add("}");
		
		result.add("/**");
		result.add("* 根据ID删除"+obj.getObjComment());
		result.add("* @param id	");
		result.add("* @return ");
		result.add("*/");
		result.add("@Transactional");
		result.add("public Boolean  delete"+obj.getObjName()+"ById(Long id){");
		result.add("	Integer mark = this."+TransUtil.lowerCase(obj.getObjName())+"Dao.deleteById(id)");
		result.add("	return (mark.intValue() == 0)?Boolean.FALSE:Boolean.TRUE;");
		result.add("}");

		result.add("/**");
		result.add("* 根据ids删除"+obj.getObjComment());
		result.add("* @param ids	");
		result.add("* @return ");
		result.add("*/");
		result.add("@Transactional");
		result.add("public Boolean  delete"+obj.getObjName()+"ByIds(List<Long> ids){");
		result.add("	Integer mark = this."+TransUtil.lowerCase(obj.getObjName())+"Dao.deleteByIds(ids)");
		result.add("	return (mark.intValue() == ids.size)?Boolean.FALSE:Boolean.TRUE;");
		result.add("}");
		
		result.add("/**");
		result.add("* 根据ID获取"+obj.getObjComment());
		result.add("* @param id	");
		result.add("* @return ");
		result.add("*/");
		result.add("public "+obj.getObjName()+" find("+obj.getObjName()+"ById(Long id){");
		result.add("	"+obj.getObjName()+" entity = this."+TransUtil.lowerCase(obj.getObjName())+".findById(id)");
		result.add("	return entity");
		result.add("}");
		

		

		return TransUtil.arrayList2Code(result,"\r\n");
	}
	/**
	 * 输出IService类代码
	 * @param obj
	 * @param options
	 * @return
	 */
	public static String generateControllerString(MetaGenObj obj,Map<String,String> options){
		List<String> result = new ArrayList<String>();
		result.add("package	"+obj.getObjPackageName()+".controller;");
		result.add("import java.util.List;");
		result.add("import java.util.Map;");
		result.add("import java.util.ArrayList;");
		result.add("import java.util.HashMap;");
		
		result.add("import org.slf4j.Logger;");
		result.add("import org.slf4j.LoggerFactory;");
		result.add("import org.springframework.beans.factory.annotation.Autowired;");
		result.add("import org.springframework.stereotype.Controller;");
		result.add("import org.springframework.web.bind.annotation.PathVariable;");
		result.add("import org.springframework.web.bind.annotation.RequestBody;");
		result.add("import org.springframework.web.bind.annotation.RequestMapping;");
		result.add("import org.springframework.web.bind.annotation.ResponseBody;");
		result.add("import org.springframework.web.servlet.ModelAndView;");
		result.add("import com.dwork.base.controller.BaseController;");
		result.add("import com.dwork.base.controller.entity.BaseResultObject;");
		result.add("import com.dwork.base.pagination.Page;");
		result.add("import com.dwork.base.pagination.Pagination;");
		result.add("import com.dwork.base.validate.groups.DEFAULT;");
		result.add("import "+obj.getObjPackageName()+".entity."+obj.getObjName()+";");
		result.add("import "+obj.getObjPackageName()+".service.I"+obj.getObjName()+"Service;");
		
		result.add("@Controller");
		result.add("@RequestMapping(value = \""+TransUtil.lowerCase(obj.getObjName())+"\", name = \""+obj.getObjComment()+"管理\")");
		result.add("public class "+obj.getObjName()+"Controller  extends BaseController{");
		result.add("	private static Logger logger = LoggerFactory.getLogger("+obj.getObjName()+"Controller.class);");

		result.add("	@Autowired");
		result.add("	private I"+obj.getObjName()+"Service "+TransUtil.lowerCase(obj.getObjName())+"Service;");

		result.add("	@RequestMapping(value = \"/g2manage\", name = \"进入"+obj.getObjComment()+"管理界面\")");
		result.add("	public ModelAndView manage()");
		result.add("		ModelAndView mv = getBaseMV(\"/"+TransUtil.lowerCase(obj.getObjName())+"/manage\");");
		result.add("		return mv;");
		result.add("	}");
		
		result.add("	@RequestMapping(value = \"/g2Add\", name = \"进入"+obj.getObjComment()+"新增界面\")");
		result.add("	public ModelAndView g2Add()");
		result.add("		ModelAndView mv = getBaseMV(\"/"+TransUtil.lowerCase(obj.getObjName())+"/addForm\");");
		result.add("		return mv;");
		result.add("	}");
		
		result.add("	@RequestMapping(value = \"/g2Edit/{id}\", name = \"进入"+obj.getObjComment()+"修改界面\")");
		result.add("	public ModelAndView g2Edit(@PathVariable Long id) {");
		result.add("		ModelAndView mv = getBaseMV(\"/"+TransUtil.lowerCase(obj.getObjName())+"/editForm\");");
		result.add("		if(id!=null){");
		result.add("			"+obj.getObjName()+" entity = this."+TransUtil.lowerCase(obj.getObjName())+"Service.find"+obj.getObjName()+"ById(id);");
		result.add("			mv.addObject(\"entity\", entity);");
		result.add("		}");
		result.add("		return mv;");
		result.add("	}");
		
		result.add("	@RequestMapping(value = \"/queryList\", name = \"分页查询"+obj.getObjComment()+"\")");
		result.add("	@ResponseBody");
		result.add("	public void queryList(Integer pageNum,Integer pageSize , String queryKey) {");
		result.add("		BaseResultObject baseResultObject = new BaseResultObject();");
		result.add("		Map<String, Object> paramMap = new HashMap<String,Object>();");
		result.add("		Page page = new Page();");
		result.add("		page.setCurrentPage(pageNum);");
		result.add("		page.setPageSize(pageSize);");
		result.add("		if(queryKey!=null&&!queryKey.equals(\"\")){");
		result.add("			//paramMap.put(\"someAttrNameLike\", queryKey);自行根据实际需求扩展");
		result.add("		}");
		result.add("		Map<String, Object> map = new HashMap<String, Object>();");
		result.add("		Pagination<"+obj.getObjName()+"> "+TransUtil.lowerCase(obj.getObjName())+"Page = "+TransUtil.lowerCase(obj.getObjName())+"Service.query"+obj.getObjName()+"Page(page, paramMap);");
		result.add("		if("+TransUtil.lowerCase(obj.getObjName())+"Page!=null&&"+TransUtil.lowerCase(obj.getObjName())+"Page.getData()!=null){");
		result.add("			map.put(\"rows\", "+TransUtil.lowerCase(obj.getObjName())+"Page.getData());");
		result.add("			map.put(\"pageSize\", "+TransUtil.lowerCase(obj.getObjName())+"Page.getData().size());");
		result.add("			map.put(\"total\", "+TransUtil.lowerCase(obj.getObjName())+"Page.getPage().getTotalCount());");
		result.add("		}");
		result.add("		baseResultObject.setData(map);");
		result.add("		this.putInToJsonResponse(baseResultObject);");
		result.add("	}");
	
		result.add("	@RequestMapping(value = \"/add\", name = \"添加"+obj.getObjComment()+"\")");
		result.add("	@ResponseBody");
		result.add("	public void add(@RequestBody "+obj.getObjName()+" view) {");
		result.add("		BaseResultObject baseResultObject = new BaseResultObject();");
		result.add("		List<Map<String, String>> validateMessages = new ArrayList<Map<String, String>>();");
		result.add("		baseResultObject.setStatus(BaseController.STATUS_SUCCESS);");
		result.add("		baseResultObject.setMessage(BaseController.SUCCESS_MESSAGE);");
		result.add("		validateMessages = getValidatorMessage(view, DEFAULT.class);");
		result.add("		if(validateMessages!=null&&validateMessages.size()>0) {");
		result.add("			baseResultObject.setStatus(BaseController.STATUS_FAILURE);");
		result.add("			baseResultObject.setMessage(BaseController.VALIDATE_ERROR_MESSAGE);");
		result.add("			baseResultObject.setValidateMessages(validateMessages);");
		result.add("		}else{");
		result.add("			try{");
		result.add("				view = this."+TransUtil.lowerCase(obj.getObjName())+"Service.save(view);");
		result.add("			}catch (Exception e) {");
		result.add("				logger.debug(\"后台错误:\"+e.getMessage());");
		result.add("				baseResultObject.setStatus(BaseController.STATUS_FAILURE);");
		result.add("				baseResultObject.setMessage(BaseController.COMMON_ERROR_MESSAGE);");
		result.add("			}");
		result.add("			baseResultObject.setData(view);");
		result.add("		}");
		result.add("		putInToJsonResponse(baseResultObject);");
		result.add("	}");

		result.add("	@RequestMapping(value = \"/edit\", name = \"编辑"+obj.getObjComment()+"\")");
		result.add("	@ResponseBody");
		result.add("	public void add(@RequestBody "+obj.getObjName()+" view) {");
		result.add("		BaseResultObject baseResultObject = new BaseResultObject();");
		result.add("		List<Map<String, String>> validateMessages = new ArrayList<Map<String, String>>();");
		result.add("		baseResultObject.setStatus(BaseController.STATUS_SUCCESS);");
		result.add("		baseResultObject.setMessage(BaseController.SUCCESS_MESSAGE);");
		result.add("		"+obj.getObjName()+" entity = this."+TransUtil.lowerCase(obj.getObjName())+"Service.find"+obj.getObjName()+"ById(view.getId());");
		for(MetaGenAttr attr :obj.getMetaAttrs()){
			switch(attr.getRelationShip()){
				case MetaGenAttr.RELATIONSHIP_NN:
					break;
				case MetaGenAttr.RELATIONSHIP_1N:
					break;	
				case MetaGenAttr.RELATIONSHIP_N1:
					result.add("		entity.set"+TransUtil.upperCase(attr.getAttrName())+"(view.get"+TransUtil.upperCase(attr.getAttrName())+"())");
					break;
				default:
					result.add("		entity.set"+TransUtil.upperCase(attr.getAttrName())+"(view.get"+TransUtil.upperCase(attr.getAttrName())+"())");
			}
		}
		result.add("		validateMessages = getValidatorMessage(entity, DEFAULT.class);");
		result.add("		if(validateMessages!=null&&validateMessages.size()>0) {");
		result.add("			baseResultObject.setStatus(BaseController.STATUS_FAILURE);");
		result.add("			baseResultObject.setMessage(BaseController.VALIDATE_ERROR_MESSAGE);");
		result.add("			baseResultObject.setValidateMessages(validateMessages);");
		result.add("		}else{");
		result.add("			try{");
		result.add("				view = this."+TransUtil.lowerCase(obj.getObjName())+"Service.update(view);");
		result.add("			}catch (Exception e) {");
		result.add("				logger.debug(\"后台错误:\"+e.getMessage());");
		result.add("				baseResultObject.setStatus(BaseController.STATUS_FAILURE);");
		result.add("				baseResultObject.setMessage(BaseController.COMMON_ERROR_MESSAGE);");
		result.add("			}");
		result.add("			baseResultObject.setData(view);");
		result.add("		}");
		result.add("		putInToJsonResponse(baseResultObject);");
		result.add("	}");

		result.add("	@RequestMapping(value = \"/delete\", name = \"删除"+obj.getObjComment()+"\")");
		result.add("	@ResponseBody");
		result.add("	public void delete(@RequestBody List<Long> ids) {");
		result.add("		BaseResultObject baseResultObject = new BaseResultObject();");
		result.add("		baseResultObject.setStatus(BaseController.STATUS_SUCCESS);");
		result.add("		baseResultObject.setMessage(BaseController.SUCCESS_MESSAGE);");
		result.add("		try{");
		result.add("			view = this."+TransUtil.lowerCase(obj.getObjName())+"Service.delete"+obj.getObjName()+"ByIds(ids);");
		result.add("		}catch (Exception e) {");
		result.add("			logger.debug(\"后台错误:\"+e.getMessage());");
		result.add("			baseResultObject.setStatus(BaseController.STATUS_FAILURE);");
		result.add("			baseResultObject.setMessage(BaseController.COMMON_ERROR_MESSAGE);");
		result.add("		}");
		result.add("	}");
		
		result.add("}");
		return TransUtil.arrayList2Code(result,"\r\n");
	}
	
	/**
	 * 找出在生成实体对象时，所需要的元属性代码List的Map
	 * @param obj
	 * @param attr
	 * @param options
	 * @return
	 */
	public static Map<String,List<String>> generateAttr4Obj(MetaGenObj obj,MetaGenAttr attr,Map<String,String> options){
		Map<String,List<String>> attr4ObjMap = new HashMap<String,List<String>>();
		options = fixConfig(attr.getConfig(),options);
		List<String> importList = new ArrayList<String>();
		List<String> commentList = new ArrayList<String>();
		List<String> validateList = new ArrayList<String>();
		List<String> attrBody = new ArrayList<String>();
		List<String> getsList = new ArrayList<String>();
		List<String> setsList = new ArrayList<String>();
		
		String attrString = "	private ";
		String typeString = "";
		if(MetaGenAttr.RELATIONSHIP_1N.equals(attr.getRelationShip()) || MetaGenAttr.RELATIONSHIP_NN.equals(attr.getRelationShip())){
			if(attr.getRelationType()!=null && !"".equals(attr.getRelationType())){
				importList.add("import	java.util."+attr.getRelationType()+";");
				typeString+=attr.getRelationType()+"<"+attr.getAttrShortTypeName()+"> ";
			}else{
				importList.add("import	java.util.List;");
				typeString+=MetaGenAttr.RELATIONTYPE_LIST+"<"+attr.getAttrShortTypeName()+"> ";
			}
		}else{
			typeString +=attr.getAttrShortTypeName()+" ";
		}
		importList.add("import	"+attr.getAttrType()+";");
		//处理备注
		if(options.get(MetaGenAttr.CFG_KEY_COMMENT) != null){
			commentList.addAll(formatCommentList(options.get(MetaGenAttr.CFG_KEY_COMMENT)));
		}else{
			commentList.addAll(formatCommentList(attr.getAttrComment()));
		}
		//处理验证的标注
		if(options.get(MetaGenAttr.CFG_KEY_VALIDATES) != null){
			validateList.addAll(TransUtil.splitWord(options.get(MetaGenAttr.CFG_KEY_VALIDATES)));
		}
		attrString +=typeString+attr.getAttrName()+" ;";
		
		attrBody.add(attrString);
		
		getsList.add("	public "+typeString +" get"+TransUtil.upperCase(attr.getAttrName())+"() {");
		getsList.add("		return "+attr.getAttrName()+" ;");
		getsList.add("	} ");
		setsList.add("	public void" +" set"+TransUtil.upperCase(attr.getAttrName())+"("+typeString+" "+attr.getAttrName()+") {");
		setsList.add("		this."+attr.getAttrName()+" = "+attr.getAttrName()+" ;");
		setsList.add("	} ");
		attr4ObjMap.put("importList", importList);
		attr4ObjMap.put("commentList", commentList);
		attr4ObjMap.put("validateList", validateList);
		attr4ObjMap.put("attrBody", attrBody);
		attr4ObjMap.put("getsList", getsList);
		attr4ObjMap.put("setsList", setsList);
		
		return attr4ObjMap;
		
	}
	/**
	 * 混合配置文件，继承OPTION中的配置，再用当前的CONFIG中的配置替换
	 * @param config
	 * @param option
	 * @return
	 */
	public static Map<String,String> fixConfig(MetaGenConfig config,Map<String,String> defaultOption){
		Map<String,String> options = new HashMap<String,String>();
		if(defaultOption!=null && !defaultOption.isEmpty()){
			options = defaultOption;
		}
		if(config!=null && config.getItems()!=null && config.getItems().size()>0){
			for(MetaGenConfigItem item : config.getItems()){
				options.put(item.getItemKey(), item.getItemValue());
			}
		}
		return options;
	}
	/**
	 * 根据纯注释单行字符串，生成相应的JAVA注释格式。
	 * @param pureComment
	 * @return
	 */
	public static List<String> formatCommentList(String pureComment){
		return formatCommentList(TransUtil.splitWord(pureComment));
	}
	/**
	 * 根据纯注释列表，生成相应的JAVA注释格式
	 * @param pureComments
	 * @return
	 */
	public static List<String> formatCommentList(List<String> pureComments){
		List<String>  comments = new ArrayList<String>();
		comments.add("/**");
		for(String pureComment:pureComments){
			comments.add("* "+pureComment);
		}
		comments.add("*/");
		return comments;
	}
	
	/**
	 * 常用javaType对应myibatis的jdbcType
	 * @param javaType
	 * @return
	 */
	public static String javaType2JdbcType(String javaType){
		String jdbcType = "";
		
		switch(javaType){
			case "java.lang.String":
				jdbcType="VARCHAR";//jdbcType="LONGVARCHAR";jdbcType="CHAR";一般VARCHAR用得多
				break;
			case "java.lang.Integer":
				jdbcType="NUMERIC";
				break;
			case "java.lang.Long":
				jdbcType="NUMERIC";
				break;
			case "java.lang.Double":
				jdbcType="DOUBLE";
				break;
			case "java.lang.Boolean":
				jdbcType="BOOLEAN";
				break;
			case "java.math.BigDecimal":
				jdbcType="NUMERIC";
				break;
			case "java.sql.Blob":
				jdbcType="BLOB";
				break;
			case "java.sql.Clob":
				jdbcType="CLOB";
				break;
			case "java.util.Date":
				jdbcType="DATE";
				break;
		}
		return jdbcType;
	}
	/**
	 * 常用myibatis的jdbcType转oracle字段类型
	 * @param jdbcType
	 * @return
	 */
	public static String jdbcType2OracleType(String jdbcType){
		String oracleType = "";
		
		switch(jdbcType){
			case "VARCHAR":
				oracleType="VARCHAR";
				break;
			case "NUMERIC":
				oracleType="NUMBER";
				break;
			
			case "DOUBLE":
				oracleType="NUMBER";
				break;
			case "BOOLEAN":
				oracleType="CHAR";
				break;
			
			case "BLOB":
				oracleType="BLOB";
				break;
			case "CLOB":
				oracleType="CLOB";
				break;
			case "DATE":
				oracleType="DATE";
				break;
			case "LONGVARCHAR":
				oracleType="LONG";
				break;
		}
		return oracleType;
	}
	/**
	 * 常用myibatis的jdbcType转mysql字段类型
	 * @param jdbcType
	 * @return
	 */
	public static String jdbcType2MysqlType(String jdbcType){
		String mysqlType = "";
		
		switch(jdbcType){
			case "VARCHAR":
				mysqlType="VARCHAR";
				break;
			case "NUMERIC":
				mysqlType="NUMERIC";
				break;
			case "DOUBLE":
				mysqlType="DOUBLE";
				break;
			case "BOOLEAN":
				mysqlType="CHAR";
				break;
			case "BLOB":
				mysqlType="BLOB";
				break;
			case "CLOB":
				mysqlType="CLOB";
				break;
			case "DATE":
				mysqlType="DATE";
				break;
			case "LONGVARCHAR":
				mysqlType="VARCHAR";
				break;
		}
		return mysqlType;
	}
	
//	Mybatis	JdbcType	Oracle	MySql
//	JdbcType	ARRAY	 	 
//	JdbcType	BIGINT	 	BIGINT
//	JdbcType	BINARY	 	 
//	JdbcType	BIT	 	BIT
//	JdbcType	BLOB	BLOB	BLOB
//	JdbcType	BOOLEAN	 	 
//	JdbcType	CHAR	CHAR	CHAR
//	JdbcType	CLOB	CLOB	CLOB
//	JdbcType	CURSOR	 	 
//	JdbcType	DATE	DATE	DATE
//	JdbcType	DECIMAL	DECIMAL	DECIMAL
//	JdbcType	DOUBLE	NUMBER	DOUBLE
//	JdbcType	FLOAT	FLOAT	FLOAT
//	JdbcType	INTEGER	INTEGER	INTEGER
//	JdbcType	LONGVARBINARY	 	 
//	JdbcType	LONGVARCHAR	LONG VARCHAR	 
//	JdbcType	NCHAR	NCHAR	 
//	JdbcType	NCLOB	NCLOB	 
//	JdbcType	NULL	 	 
//	JdbcType	NUMERIC	NUMERIC/NUMBER	NUMERIC/
//	JdbcType	NVARCHAR	 	 
//	JdbcType	OTHER	 	 
//	JdbcType	REAL	REAL	REAL
//	JdbcType	SMALLINT	SMALLINT	SMALLINT
//	JdbcType	STRUCT	 	 
//	JdbcType	TIME	 	TIME
//	JdbcType	TIMESTAMP	TIMESTAMP	TIMESTAMP
//	JdbcType	TINYINT	 	TINYINT
//	JdbcType	UNDEFINED	 	 
//	JdbcType	VARBINARY	 	 
//	JdbcType	VARCHAR	VARCHAR	VARCHAR
	/**
	 * 根据JAVA对象以及KEY，从配置里取相应
	 * @param obj
	 * @param key
	 * @return
	 */
	public static String getObjConfigItemValueByKey(MetaGenObj obj,String key){
		String value="";
		if(obj.getConfig()!=null && obj.getConfig().getItems()!=null && obj.getConfig().getItems().size()>0){
			for(MetaGenConfigItem item:obj.getConfig().getItems()){
				if(key.equals(item.getItemKey())){
					value = item.getItemValue();
					break;
				}
			}
		}
		return value;
	}
	
	public static String getAttrConfigItemValueByKey(MetaGenAttr attr,String key){
		String value="";
		if(attr.getConfig()!=null && attr.getConfig().getItems()!=null && attr.getConfig().getItems().size()>0){
			for(MetaGenConfigItem item:attr.getConfig().getItems()){
				if(key.equals(item.getItemKey())){
					value = item.getItemValue();
					break;
				}
			}
		}
		return value;
	}

}
